package pl.edu.pw.elka.tinyrepo.gate.server;

import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.Socket;
import java.util.Map;

import pl.edu.pw.elka.tinyrepo.common.CatalogContent;
import pl.edu.pw.elka.tinyrepo.common.CatalogContentSerializer;
import pl.edu.pw.elka.tinyrepo.common.HTTPHeaderType;
import pl.edu.pw.elka.tinyrepo.common.Request;
import pl.edu.pw.elka.tinyrepo.common.RequestHandler;
import pl.edu.pw.elka.tinyrepo.common.Response;
import pl.edu.pw.elka.tinyrepo.common.StatusCode;
import pl.edu.pw.elka.tinyrepo.common.exceptions.WrongPathException;
import pl.edu.pw.elka.tinyrepo.gate.descriptor.CatalogDescriptor;
import pl.edu.pw.elka.tinyrepo.gate.descriptor.Descriptor;
import pl.edu.pw.elka.tinyrepo.gate.descriptor.FileDescriptor;
import pl.edu.pw.elka.tinyrepo.gate.descriptor.RepoDescriptor;


/**
 * @author: Kajot
 */

class GETRequestHandler extends GateRequestHandler {
   
   public GETRequestHandler(RepoDescriptor desc) {
      super(desc);
   }
   
   @Override
   public void run() {
	   
      OutputStream out = null;
      
      try { 
         out = incomming.getOutputStream(); 		// wyjscie do klienta
         String requestPath = request.getPath(); 	// zadany w requescie plik/katalog

         Descriptor d = desc.getFileOrDirectoryDesc(requestPath); 
         
         // Proba pobrania pliku
         if(d.getClass() == FileDescriptor.class) {
        	 
            FileDescriptor fd = (FileDescriptor)d;
            
            // Wyslanie info o serwerze na ktorym znajduje sie zadany plik
            Response rs = new Response(StatusCode.MOVED_PERMANENTLY); 
            rs.addHeader(HTTPHeaderType.LOCATION, fd.getDestination()+"/"+fd.getId());
            rs.write(out);
            
            System.out.println("Redirected "+incomming+" to: "+fd.getDestination()+"/"+fd.getId());
            System.out.println("Sent response: \n"+rs);
            return;
            
         }
         
         // Proba wylistowania katalogu
         if(d.getClass() == CatalogDescriptor.class) {

         	CatalogDescriptor cd = (CatalogDescriptor) d;

        	System.out.println("Creating childs list...");
        	
        	CatalogContent content = new CatalogContent(); // generowany obiekt odpowiedzi na zadanie
        	Map<String, Descriptor> childs =  cd.getChilds(); // lista obiektow w zadanym katalogu
        	
        	// Dodanie wszystkich obiektow z zadanego katalogu do odpowiedzi
        	// z podzialem na katalogi oraz pliki
        	for(Map.Entry<String, Descriptor> entry: childs.entrySet())
        	{
        		
        		if(entry.getValue().getClass() == FileDescriptor.class)
        		{
        			content.addFile(entry.getKey());
        			continue;
        		}
        		if(entry.getValue().getClass() == CatalogDescriptor.class)
        		{
        			content.addCatalog(entry.getKey());
        			continue;
        		}
        		
        		System.out.println("Child that is not file nor catalog!");
        		
        	}
        	
        	// Serializacja odpowiedzi dla klienta
        	CatalogContentSerializer serializer = new CatalogContentSerializer();
        	String serializedCatalogContent = serializer.toXML(content);
        	
        	// Wyslanie odpowiedzi do klienta
            Response rs = new Response(StatusCode.OK);
            rs.addHeader(HTTPHeaderType.CONTENT_TYPE, "text/xml");
            rs.addHeader(HTTPHeaderType.CONTENT_LENGTH, Integer.toString(serializedCatalogContent.length()));
            rs.write(out);
            System.out.println("Sent response: \n"+rs);
            System.out.println("Response header sent, sending serialized CatalogContent object...");
            
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out));
            writer.write(serializedCatalogContent);
            writer.flush();
            System.out.println("Sent.");
            return;
            
         }
         
      }catch (FileNotFoundException e) { // pliku nie ma
         Response rs = new Response(StatusCode.NOT_FOUND);
         rs.write(out);
      }
      catch (WrongPathException e) { // nieprawidlowa sciezka do pliku
         Response rs = new Response(StatusCode.NOT_FOUND);
         rs.write(out);
      }
      catch (IOException e) {
         // cos nie tak z polaczeniem, nic nie wysylaj, wyswietl info na serwerze
         e.printStackTrace();
      }
      // socket jest zamykany w klasach DAVServer
   }


   @Override
   public RequestHandler copy() {
      return new GETRequestHandler(desc);
   }
   
   
}
